home *** CD-ROM | disk | FTP | other *** search
/ Developer Helper 1: Phil & Dave's Excellent CD / Excellent CD HFS.raw / Moof / Goodies / DTS Goodies / Bechtels stuff / Play.c < prev    next >
C/C++ Source or Header  |  1988-08-29  |  12KB  |  454 lines

  1. /* File:    Play.c
  2.  * Purpose:    demonstrate Apple CD SC control
  3.  * Date:    17 June 1988
  4.  * Comments:
  5.  *            This code is written for LightSpeed C version 2.15
  6.  *            Create a project with this source plus MacTraps.
  7.  *            Requires some associated resources (in the file Play.r).
  8.  *            With this program on your hard disk, you can click
  9.  *            on a track on an Audio CD and the CD SC drive will
  10.  *            start audio play, beginning at that track and continuing
  11.  *            to the end of the disc.
  12.  *
  13.  * Revisions:
  14.  *
  15.  *            Converted to converted to mpw 3.0 8/29 mb
  16.  *
  17.  *    Build instructions:    
  18.  *
  19.  *        rez -c MBAU :RIncludes:Types.r Play.r  -o Play     
  20.  *        c Play.c -w                            
  21.  *        link Play.c.o -o Play -c aucd ∂
  22.  *           "{CLibraries}"CRuntime.o ∂
  23.  *           "{CLibraries}"CInterface.o ∂
  24.  *           "{Libraries}"Interface.o
  25.  *        
  26.  *
  27.  */
  28.  
  29. #include <types.h>         /* Nearly always required */
  30. #include <quickdraw.h>     /* To access the qd globals */
  31. #include <fonts.h>         /* Only for InitFonts() trap */
  32. #include <events.h>        /* GetNextEvent(), ... */
  33. #include <windows.h>    /* GetNewWindow(), ... */
  34. #include <dialogs.h>    /* InitDialogs() and GetNewDialog() */
  35. #include <menus.h>         /* EnableItem(), DisableItem() */
  36. #include <desk.h>        /* SystemTask(), SystemClick() */
  37. #include <TextEdit.h>
  38. #include <Resources.h>    /* GetResource() */
  39. #include <OSUtils.h>    /* SysBeep() */
  40. #include <ToolUtils.h>
  41. #include <SegLoad.h>
  42. #include <Strings.h>
  43. #include <Devices.h>
  44. #include <Files.h>
  45. #include <Packages.h>
  46.  
  47. #include <Memory.h>
  48. #include <OSEvents.h>
  49.  
  50. /* Some constants, from the CD SC Developer's Guide chapter 7 */
  51. #define    TRACKADDR    2
  52. #define    STEREO        9
  53. #define    INPROGRESS    0
  54.  
  55. /* Some commands, from the CD SC Developer's Guide chapter 7 */
  56. #define    APLAY    104
  57. #define    ASTOP    106
  58. #define ASTATUS    107
  59.  
  60. /* The resource ID I use for my error dialog */
  61. #define errorID    128
  62.  
  63. /* prototype function declarations. */
  64. void    Error(char *, short);
  65. void    ExtractTrackNo(char *, short *);
  66. OSErr    AStop(short, short);
  67. OSErr    APlay(short, short);
  68. OSErr    Play(char *, short);
  69. short    GetDrvRefNum(short);
  70. void    PlayOnStartup(short);
  71. Boolean    AskAndPlay(void);
  72. void    main(void);
  73. pascal void Debugger(/*void*/) extern 0xA9FF;
  74.  
  75. /************************************************************************
  76.  *
  77.  *  Function:        Error
  78.  *
  79.  *  Purpose:        Report an error to the user.
  80.  *
  81.  *  Returns:        nothing
  82.  *
  83.  *  Side Effects:    none.
  84.  *
  85.  *  Description:    Takes a string and a result code.  Convert the result
  86.  *                    into a pascal string using NumToString() and then just
  87.  *                    do a switch to determine which friendly error message
  88.  *                    to put up on the screen.  ParamText() sets up the alert
  89.  *                    so that it has the correct information.  Use Alert() to 
  90.  *                    actually display the message to the user.
  91.  *
  92.  ************************************************************************/
  93. void
  94. Error(where, result)
  95. char    *where;
  96. short    result;
  97. {
  98.     DialogPtr    dPtr;
  99.     short        itemhit;
  100.     Str255        strResult;
  101.     long        longResult;
  102.     
  103.     longResult = result;
  104.     NumToString(longResult, strResult);
  105.     
  106.     switch (result)
  107.     {
  108.         case -56:
  109.             ParamText(where, strResult, "\pSpecified drive number doesn't match any number in the drive queue.", "\p");
  110.             break;
  111.         case -51:
  112.             ParamText(where, strResult, "\pReference number specifies nonexistent access path.", "\p");
  113.             break;
  114.         case -50:
  115.             ParamText(where, strResult, "\pError in parameter list.", "\p");
  116.             break;
  117.         case -43:
  118.             ParamText(where, strResult, "\pFile not found.", "\p");
  119.             break;
  120.         case -36:
  121.             ParamText(where, strResult, "\pI/O error.", "\p");
  122.             break;
  123.         case -35:
  124.             ParamText(where, strResult, "\pNo such volume.", "\p");
  125.             break;
  126.         case -21:
  127.             ParamText(where, strResult, "\pBad unit number.", "\p");
  128.             break;
  129.         default:
  130.             ParamText(where, strResult, "\p", "\p");
  131.             break;
  132.     }
  133.     
  134.     Alert(errorID, (ProcPtr) NULL);
  135. }
  136.  
  137.               
  138. /************************************************************************
  139.  *
  140.  *  Function:        ExtractTrackNo
  141.  *
  142.  *  Purpose:        Extract track number in BCD from PString
  143.  *
  144.  *  Returns:        nothing
  145.  *
  146.  *  Side Effects:    *track gets a new value
  147.  *
  148.  *  Description:    Extract track number in BCD from PString "name".
  149.  *                    "name" is always of the form "Track XX", where XX
  150.  *                    ranges from " 1" (1 with a leading space) to "99"
  151.  *                    (You can't have more than 99 tracks on a compact disc.
  152.  *                    Bet you didn't know that, did you?  Right in the "Yellow
  153.  *                    Book" specification of compact disc encoding.)
  154.  *
  155.  ************************************************************************/
  156. void
  157. ExtractTrackNo(name, track)
  158. char        *name;
  159. short        *track;
  160. {
  161.     short    size;
  162.     short    t;
  163.         
  164.     t = 0;
  165.     size = *name;
  166.     if (name[size-1] != ' ')
  167.         t = (name[size-1] - '0') * 16;
  168.     t += name[size] - '0';
  169.     
  170.     *track = t;    
  171. }
  172.  
  173. /************************************************************************
  174.  *
  175.  *  Function:        AStop
  176.  *
  177.  *  Purpose:        stop playing an audio track
  178.  *
  179.  *  Returns:        OSErr.  Probably either
  180.  *                        noErr        everything's hunky-dory!
  181.  *                        paramErr    you messed up the call somehow.
  182.  *
  183.  *  Side Effects:    stops play.
  184.  *
  185.  *  Description:    The track that you pass in is the LAST track that you
  186.  *                    want to have play.  This means that if you wanted to
  187.  *                    play only one track, you'd pass the same value to
  188.  *                    this routine and APlay() [q.v.]
  189.  *
  190.  *                    Note that this routine isn't called in this sample,
  191.  *                    but it's included for your enjoyment.
  192.  *
  193.  ************************************************************************/
  194. OSErr
  195. AStop(track, refNum)
  196. short    track;
  197. short    refNum;
  198. {
  199.     struct {
  200.         short    addrFormat;
  201.         long    address;
  202.     }    csParam;
  203.     
  204.     csParam.addrFormat = TRACKADDR;
  205.     csParam.address = track;
  206.     return (Control(refNum, ASTOP, &csParam));
  207. }
  208.  
  209. /************************************************************************
  210.  *
  211.  *  Function:        APlay
  212.  *
  213.  *  Purpose:        start playing an audio track
  214.  *
  215.  *  Returns:        OSErr.  Probably either
  216.  *                        noErr        everything's hunky-dory!
  217.  *                        paramErr    you messed up the call somehow.
  218.  *
  219.  *  Side Effects:    starts play.  By default, this will play until the
  220.  *                    end of the disc.
  221.  *
  222.  *  Description:    The track that you pass in is the first track that you
  223.  *                    want to have play.
  224.  *
  225.  ************************************************************************/
  226. OSErr
  227. APlay(track, refNum)
  228. short    track;
  229. short    refNum;
  230. {
  231.     struct {
  232.         short    addrFormat;
  233.         long    address;
  234.         short    stopAddress;
  235.         short    playMode;
  236.     }    csParam;
  237.     
  238.     csParam.addrFormat = TRACKADDR;
  239.     csParam.address = track;    /* must be in BCD */
  240.     csParam.stopAddress = 0;
  241.     csParam.playMode = STEREO;
  242.     return (Control(refNum, APLAY, &csParam));
  243. }
  244.  
  245.  
  246. /************************************************************************
  247.  *
  248.  *  Function:        Play
  249.  *
  250.  *  Purpose:        play a track, given it's "filename"
  251.  *
  252.  *  Returns:        OSErr
  253.  *                        whatever is returned by APlay()
  254.  *
  255.  *  Side Effects:    starts play of the audio track.
  256.  *
  257.  *  Description:    The two parameters passed in are the file name (which
  258.  *                    will always be of the form "Track XX", XX varying from
  259.  *                    " 1" to "99") and the driver reference number. Extract
  260.  *                    the track number and use it to call APlay() [q.v.]
  261.  *
  262.  ************************************************************************/
  263. OSErr
  264. Play(name, driveNumber)
  265. char         *name;
  266. short        driveNumber;
  267. {
  268.     short    trackno;
  269.     OSErr    result;
  270.     
  271.     ExtractTrackNo(name, &trackno);
  272.     return( APlay(trackno, driveNumber) );
  273. }
  274.  
  275.  
  276. /************************************************************************
  277.  *
  278.  *  Function:        GetDrvRefNum
  279.  *
  280.  *  Purpose:        Get the driver reference number
  281.  *
  282.  *  Returns:        short.  The driver reference number
  283.  *
  284.  *  Side Effects:    none.
  285.  *
  286.  *  Description:    PBHGetVInfo() will retrieve the driver reference
  287.  *                    number, given the vRefNum associated with a file.
  288.  *                    We acquired the vRefNum as something passed into
  289.  *                    the program, either by SFGetFile() or by 
  290.  *                    GetAppFile().
  291.  *
  292.  *                    We'll use the driver reference number in all our
  293.  *                    control calls to the driver.
  294.  *
  295.  ************************************************************************/
  296. short
  297. GetDrvRefNum(vRefNum)
  298. short    vRefNum;
  299. {
  300.     HParamBlockRec    io;
  301.     
  302.     io.volumeParam.ioCompletion = NULL;
  303.     io.volumeParam.ioNamePtr = NULL;
  304.     io.volumeParam.ioVRefNum = vRefNum;
  305.     io.volumeParam.ioVolIndex = 0;
  306.     PBHGetVInfo(&io, false);
  307.     return io.volumeParam.ioVDRefNum;
  308. }
  309.  
  310.  
  311.  
  312. /************************************************************************
  313.  *
  314.  *  Function:        PlayOnStartup
  315.  *
  316.  *  Purpose:        Play the files passed in to our application
  317.  *
  318.  *  Returns:        nothing
  319.  *
  320.  *  Side Effects:    plays some files.
  321.  *
  322.  *  Description:    Loop, using GetAppFiles() to get the next "file"
  323.  *                    (actually audio CD track) to play.  Continue until
  324.  *                    we run out of files to play or until we get some
  325.  *                    error while trying to play a track.
  326.  *
  327.  *                    Exercise to the programmer:
  328.  *                    As this routine is currently written, it doesn't
  329.  *                    handle opening multiple tracks at once.  (e.g. the
  330.  *                    user selects five tracks and opens them all.)  Right
  331.  *                    now, you'll only hear the last track (each Play()
  332.  *                    command cancels the previous one.)
  333.  *
  334.  *                    Add a routine to check the status of the CD SC 
  335.  *                    drive (using AStatus) so that you wait for a track
  336.  *                    to finish before starting the next track.
  337.  *
  338.  ************************************************************************/
  339. void
  340. PlayOnStartup(count)
  341. short    count;
  342. {
  343.     short    i;
  344.     AppFile    app;
  345.     OSErr    result;
  346.  
  347.     for (i = 0; i++<count; )
  348.     {
  349.         GetAppFiles(i, &app);
  350.         if (app.fType == 'trak')
  351.         {
  352.             result = Play((char *)app.fName, GetDrvRefNum(app.vRefNum));
  353.             if (result != noErr)
  354.                 Error("\pPlay returned", result);
  355.         }
  356.     }
  357. }
  358.  
  359.  
  360. /************************************************************************
  361.  *
  362.  *  Function:        AskAndPlay
  363.  *
  364.  *  Purpose:        Prompt the user for a track and play it
  365.  *
  366.  *  Returns:        Boolean.  Either:
  367.  *                        true    the user wants us to continue
  368.  *                        false    the user wants us to exit, or an error
  369.  *                                occurred.
  370.  *
  371.  *  Side Effects:    may play a track.
  372.  *
  373.  *  Description:    Use SFGetFile() with a specific type ('trak') to get
  374.  *                    a list of just audio CD tracks.  If the user selects
  375.  *                    an audio CD track, play it.
  376.  *
  377.  ************************************************************************/
  378. Boolean
  379. AskAndPlay()
  380. {
  381.     SFReply    sf;
  382.     short    refnum;
  383.     static Point where = {100,100};
  384.     static OSType sftl = 'trak';
  385.     Boolean result;
  386.     OSErr    errorCode;
  387.     
  388.     result = true;
  389.     FlushEvents(everyEvent-diskMask,0);
  390.     SFGetFile(where, "\pSelect Track to Play", (ProcPtr)NULL,
  391.         1, &sftl, (ProcPtr)NULL, &sf);
  392.     if (!sf.good)
  393.         result = false;
  394.     else
  395.     {
  396.         errorCode = Play((char *)sf.fName, GetDrvRefNum(sf.vRefNum));
  397.         if (errorCode != noErr)
  398.         {
  399.             Error("\pPlay returned", result);
  400.             result = false;
  401.         }
  402.     }
  403.     return result;
  404. }
  405.  
  406.  
  407. /************************************************************************
  408.  *
  409.  *  Function:        main
  410.  *
  411.  *  Purpose:        The Master Cylinder.   This is where we start.
  412.  *
  413.  *  Returns:        nothing.
  414.  *
  415.  *  Side Effects:    does whatever you tell it.
  416.  *
  417.  *  Description:    Do the standard Macintosh initialization.  Following
  418.  *                    all the boilerplate, use CountAppFiles() to see how
  419.  *                    we were started.  We could be started one of three
  420.  *                    ways:
  421.  *                    1)  The user opened our application.  We will have 
  422.  *                        a count of zero.  Go ask the user for a track.
  423.  *                    2)    The user opened an audio CD track "file".  We
  424.  *                        will have a non-zero count.  Go play the track(s)
  425.  *                        that the user asked.
  426.  *
  427.  ************************************************************************/
  428. void
  429. main()
  430. {
  431.     short    message, count;
  432.     short    refNum;
  433.     
  434.     MaxApplZone();
  435.     MoreMasters();
  436.  
  437.     InitGraf(&qd.thePort);
  438.     InitFonts();
  439.     InitWindows();
  440.     InitMenus();
  441.     TEInit();
  442.     InitDialogs(0);
  443.  
  444.     InitCursor();
  445.     FlushEvents(everyEvent-diskMask,0);
  446.  
  447.     CountAppFiles(&message, &count);
  448.     if (count)
  449.         PlayOnStartup(count);
  450.     else
  451.         while (AskAndPlay())
  452.             ;                /* null loop */
  453. }
  454.